/*
* 使用方法：
* 提交表单前验证：jQuery('.validate').validate({submit:true}) 返回：true | false;
* 内置验证：在class中加入属性
* required：必需字段
* min：最小值，使用：min-32，或min--32
* max：最大值，使用：max-50
* minlength：最小长度，使用：minlength-15
* maxlength：最大长度，使用：maxlength-30
* word：英文字符、数字、下划线
* methodname：英文字符、数字、下划线，数字不能开头
* javamethodname：中英文字符、数字、下划线，数字不能开头
* url、email、date、dateiso、accept、
* datecn：日期格式：yyyy-MM-dd
* dateau：日期格式：dd-MM-yyyy
* chinese：中文
* number：数字
* filename：文件名[中英文数字下划线.英文]
* tolowercase：自动转换为小写字符
* touppercase：自动转换为大写字符
*/
;(function($){
	$.fn.extend({
		validate: function(options) {
			if(options && options.submit==true){
				var validator = new $.validator();
				var test = true;
				$(this).each(function(index){
					var a = validator.element(this);
					test =  test && a;
				});
				return test;
			}else{
				var validator = new $.validator();
				function delegate(event) {
					validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
				}
				$(this)
					.delegate("focusin focusout keyup click change", ":text, :password, :file, select, textarea", delegate)
					.delegate("click", ":radio, :checkbox", delegate);
			}
			return false;
		}
	});
})(jQuery);
//validator
;(function($){
	$.extend({
		format : function(source, params) {
			if ( arguments.length == 1 )
				return function() {
					var args = $.makeArray(arguments);
					args.unshift(source);
					return $.format.apply( this, args );
				};
			if ( arguments.length > 2 && params.constructor != Array  ) {
				params = $.makeArray(arguments).slice(1);
			}
			if ( params.constructor != Array ) {
				params = [ params ];
			}
			$.each(params, function(i, n) {
				source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
			});
			return source;
		}
	});
})(jQuery);
//custome selector
;(function($){
	$.extend({
		validator : function( options, form ) {
			this.settings = $.extend( {}, $.validator.defaults, options );
		}
	});
	$.extend($.validator,{
		defaults: {
			messages: {},
			groups: {},
			rules: {},
			errorClass: "error",
			errorElement: "label",
			focusInvalid: true,
			errorContainer: $( [] ),
			errorLabelContainer: $( [] ),
			onsubmit: true,
			ignore: [],
			ignoreTitle: false,
			onfocusin: function(element) {
				this.element(element);
			},
			onfocusout: function(element) {
				this.element(element);
			},
			onkeyup: function(element) {
				if(!document.all){
					this.element(element);
				}
			},
			onclick: function(element) {
				this.element(element);
			},
			onchange: function(element) {
				if(document.all){
					this.element(element);
				}
			}
		},
		prototype: {
			init: function(){
			},
			getClasses: function(element){
				return $(element).attr('class').toLowerCase().split(/\s/);
			},
			element: function(element){
				var $this = this;
				var valid=true;
				var debug ='';
				var classes = $this.getClasses(element);
				var message="";
				//debug+=", classes=["+classes.join(",")+"]"
				for(var index=0;index<classes.length;index++){
					var method = classes[index];
					//debug +=", class:"+method;
					if($.validator.methods[method]){
						var test = $.validator.methods[method].call(this,element.value,element);
						valid = valid && test;
						message = $.validator.messages[method];
					}else if(method.indexOf('-')>0){
						for (var i in $.validator.tests){
							var result = $.validator.tests[i].call($this,method);
							//debug+=", method="+method;
							if(result != null){
								var param = result.slice(1);
								var test = $.validator.methods[result[0]].call(this,element.value,element,param);
								valid = valid && test;
								message = $.format($.validator.messages[result[0]],param);
								//debug+=", result[0]="+result[0]+", param=["+result.slice(1).join(",")+"], valid="+(valid==true);
							}
							if(!valid){break;}
						}
					}
					if(!valid){break;}
				}
				//$("#description").val(debug);
				$this.checkError(valid,element,message);
				return valid;
			},
			trimValue: function(element){
				return element.value;
			},
			checkable: function( element ) {
				return /radio|checkbox/i.test(element.type);
			},
			checkError: function(valid,element,message){
				var $el=$(element);
				var pos=$el.position();
				var width=$el.width();
				var after=$('<div class="validatemessage dijitTooltip dijitTooltipRight" style="opacity: 1;"><div class="dijitTooltipContainer dijitTooltipContents"></div><div class="dijitTooltipConnector"></div></div>');
				after.css({top:(pos.top)+'px',left:(pos.left+width)+'px'});
				if(!valid){
					if(!$el.hasClass('invalid')){
						$el.addClass('invalid');
					}
					if($el.next().is(".validatemessage")){
						$el.next().remove();
					}
					$el.after(after);
					after.find('.dijitTooltipContents:first').empty().append(message);
				}else{
					$el.removeClass('invalid');
					if($el.next().is(".validatemessage")){
						$el.next().remove();
					}
				}
			},
			utf8Length: function(value){
				if(!value||value.length==0){
					return 0;
				}
				var cArr = value.match(/[^\x00-\xff]/ig);
				var length = value.length + (cArr == null ? 0 : cArr.length)*2;
				cArr = null;
				return length;
			},
			optional: function(element){
				return !$(element).hasClass("required");
			},
			length: function(value){
				if(!value){
					return 0;
				}
				return value.length;
			}
		},
		methods: {
			tolowercase: function(value, element, param){
				element.value=value.toLowerCase();
				return true;
			},
			touppercase: function(value, element, param){
				element.value=value.toUpperCase();
				return true;
			},
			required: function(value, element, param) {
				switch( element.nodeName.toLowerCase() ) {
					case 'select':
						var options = $("option:selected", element);
						return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
					case 'input':
						if ( this.checkable(element) )
							return this.getLength(value, element) > 0;
					default:
						return $.trim(value).length > 0;
				}
			},
			word: function(value, element, param){
				if(this.length(value)>0){
					var reg = new RegExp("^[\\w]*$");
					return reg.test(value);
				}
				return this.optional(element);
			},
			methodname: function(value, element, param){
				var reg = new RegExp("^[a-zA-Z_]{1}[\\w]*$");
				return reg.test(value);
			},
			javamethodname: function(value, element, param){
				var test = new RegExp("^\\D+");
				var reg = new RegExp("^[\u4e00-\u9fa5\\w]+$");
				return test.test(value) && reg.test(value);
			},
			min: function(value, element, param){
				if(this.length(value)<1){
					return this.optional(element);
				}
				var val = parseFloat(value);
				if(val == NaN){
					return false;
				}
				if(param && param[0]){
					var min = parseFloat(param[0]);
					return val >= min;
				}
			},
			max: function(value, element, param){
				if(this.length(value)<1){
					return this.optional(element);
				}
				var val = parseFloat(value);
				if(val == NaN){
					return false;
				}
				if(param && param[0]){
					var max = parseFloat(param[0]);
					return val <= max;
				}
				return this.optional(element);
			},
			minlength: function(value, element, param){
				if(param && param[0]){
					var min = parseInt(param[0]);
					if(min==NaN){
						return true;
					}
					return this.utf8Length(value) >= min;
				}
				return this.optional(element);
			},
			maxlength: function(value, element, param){
				if(param && param[0]){
					var max = parseInt(param[0]);
					if(max==NaN||max<1){
						return true;
					}
					return this.utf8Length(value) <= max;
				}
				return this.optional(element);
			},
			url: function(value, element, param){
				return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
			},
			email: function(value, element, param){
				return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
			},
			date: function(value, element, param){
				return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
			},
			dateiso: function(value, element, param){
				return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
			},
			accept: function(value, element, param){
				param = typeof param == "string" ? param : "png|jpe?g|gif";
				return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
			},
			equalto: function(value, element, param){
				if(param && param[0]){
					return value == $("#"+param[0]).val();
				}
				return false;
			},
			datecn: function(value, element, param){
				if(this.length(value)>0){
					var reg = new RegExp("^(\\d{4})-(\\d{1,2})-(\\d{1,2})$");
					if(!reg.test(value)){return false;}
					var d = new Date(value.replace(reg, '$1/$2/$3'));
					return (parseInt(RegExp.$2, 10) == (1+d.getMonth())) &&
							(parseInt(RegExp.$3, 10) == d.getDate()) &&
							(parseInt(RegExp.$1, 10) == d.getFullYear() );
				}
				return this.optional(element);
			},
			dateau: function(value, element, param){
				if(this.length(value)>0){
					var reg = new RegExp("^(\\d{2})\\/(\\d{2})\\/(\\d{4})$");
					if(!reg.test(value)){return false;}
					var d = new Date(value.replace(reg, '$3/$2/$1'));
					return (parseInt(RegExp.$2, 10) == (1+d.getMonth())) &&
							(parseInt(RegExp.$1, 10) == d.getDate()) &&
							(parseInt(RegExp.$3, 10) == d.getFullYear() );
				}
				return this.optional(element);
			},
			chinese: function(value, element, param){
				if(this.length(value)>0){
					var reg = new RegExp("^[\u4e00-\u9fa5]+$");
					return reg.test(value);
				}
				return this.optional(element);
			},
			number: function(value, element, param){
				if(this.length(value)>0){
					var reg = new RegExp("^\\d+$");
					return reg.test(value);
				}
				return this.optional(element);
			},
			filename: function(value, element, param){
				if(this.length(value)>0){
					var reg = new RegExp("^[\u4e00-\u9fa5\\w]+\\.[\\w]+$");
					return reg.test(value);
				}
				return this.optional(element);
			}
		},
		tests: {
			min: function(method){
				var reg = new RegExp("^min-([-\\d]+)$");
				if(!reg.test(method)){
					return null;
				}
				var arr = new Array();
				arr[0]="min";
				arr[1]=$.trim(RegExp.$1);
				return 	arr;
			},
			max: function(method){
				var reg = new RegExp("^max-([-\\d]+)$");
				if(!reg.test(method)){
					return null;
				}
				var arr = new Array();
				arr[0]="max";
				arr[1]=$.trim(RegExp.$1);
				return 	arr;
			},
			minlength: function(method){
				var reg = new RegExp("^minlength-([-\\d]+)$");
				if(!reg.test(method)){
					return null;
				}
				var arr = new Array();
				arr[0]="minlength";
				arr[1]=$.trim(RegExp.$1);
				return 	arr;
			},
			maxlength: function(method){
				var reg = new RegExp("^maxlength-([-\\d]+)$");
				if(!reg.test(method)){
					return null;
				}
				var arr = new Array();
				arr[0]="maxlength";
				arr[1]=$.trim(RegExp.$1);
				return 	arr;
			},
			equalto: function(method){
				var reg = new RegExp("^equalto-(\\w+)$");
				if(!reg.test(method)){
					return null;
				}
				var arr = new Array();
				arr[0]="equalto";
				arr[1]=$.trim(RegExp.$1);
				return 	arr;
			}
		},
		messages: {
			required: "该项是必填项",
			word: "请输入字符为：英文字符、数字及下划线",
			methodname: "请输入字符：以英文字符或下划线开头，以及与数字组合的字符串",
			javamethodname: "请输入字符：以中文或英文字符或下划线开头，以及与数字组合的字符串",
			min: "最小值为：{0}",
			max: "最大值为：{0}",
			minlength: "最小长度为：{0}，其中非ASCII字符占三个长度",
			maxlength: "最大长度为：{0}，其中非ASCII字符占三个长度",
			url: "请输入正确的URL地址",
			email: "请输入正确的Email地址",
			date: "请输入正确的日期格式",
			dateiso: "请输入正确的日期格式",
			accept: "只允许上传：png|jpe?g|gif",
			equalto: "两次输入的值不相等",
			datecn: "请使用这样的日期格式: yyyy-mm-dd. 例如:2006-03-17",
			dateau: "请使用这样的日期格式: dd/mm/yyy. 例如:17/03/2009，表示2009年3月17日",
			chinese: "请输入中文",
			number: "请输入数字",
			filename: "请输入文件名，不含空格"
		}
	});
})(jQuery);
// Custom selectors
;(function($){
	$.extend($.expr[":"], {
		// http://docs.jquery.com/Plugins/Validation/blank
		blank: function(a) {return !$.trim(a.value);},
		// http://docs.jquery.com/Plugins/Validation/filled
		filled: function(a) {return !!$.trim(a.value);},
		// http://docs.jquery.com/Plugins/Validation/unchecked
		unchecked: function(a) {return !a.checked;}
	});
})(jQuery);
// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target

// provides triggerEvent(type: String, target: Element) to trigger delegated events
;(function($) {
	$.each({
		focus: 'focusin',
		blur: 'focusout'
	}, function( original, fix ){
		$.event.special[fix] = {
			setup:function() {
				if ( $.browser.msie ) return false;
				this.addEventListener( original, $.event.special[fix].handler, true );
			},
			teardown:function() {
				if ( $.browser.msie ) return false;
				this.removeEventListener( original,
				$.event.special[fix].handler, true );
			},
			handler: function(e) {
				arguments[0] = $.event.fix(e);
				arguments[0].type = fix;
				return $.event.handle.apply(this, arguments);
			}
		};
	});
	$.extend($.fn, {
		delegate: function(type, delegate, handler) {
			return this.bind(type, function(event) {
				var target = $(event.target);
				if (target.is(delegate)) {
					return handler.apply(target, arguments);
				}
			});
		},
		triggerEvent: function(type, target) {
			return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);
		}
	})
})(jQuery);
